﻿using System;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Xml;
using System.Drawing;



namespace SocketServer
{
    public partial class frmSocketServer : Form
    {
        public frmSocketServer()
        {
            InitializeComponent();
        }

        private void frmSocketServer_Load(object sender, EventArgs e)
        {
            this.CmdStar.Enabled = true;
            this.CmdStop.Enabled = false;

            CmdStar_Click(null, null);
        }

        //声明将要用到的类
        private IPEndPoint ServerInfo;//存放服务器的IP和端口信息
        private Socket ServerSocket;//服务端运行的SOCKET
        private Thread ServerThread;//服务端运行的线程
        private Socket[] ClientSocket;//为客户端建立的SOCKET连接
        private int ClientNumb;//存放客户端数量
        private byte[] MsgBuffer;
        private IniFile iFile = new IniFile(Application.StartupPath + "\\BrsService.ini");
        string server = "";
        string database = "";
        string uid = "";
        string pwd = "";

        private int GetPort()
        {
            try
            {
                return iFile.ReadInt("Setting","Port",6600);
            }
            catch { return 6600; }//默认是6600
        }



        private void CmdStar_Click(object sender, EventArgs e)
        {
            database = iFile.ReadString("Setting", "DataBase", "");
            uid = iFile.ReadString("Setting", "uid", "");
            pwd = iFile.ReadString("Setting", "pwd", "");
            server = iFile.ReadString("Setting", "server", "");
            if (server == "")
            {
                MessageBox.Show("数据库服务地址不能为空,请配置");
                return;
            }

            if (database == "")
            {
                MessageBox.Show("数据库不能为空,请配置");
                return;
            }

            if (uid == "")
            {
                MessageBox.Show("数据库用户名不能为空,请配置");
                return;
            }

            if (pwd == "")
            {
                MessageBox.Show("数据库密码不能为空,请配置");
                return;
            }

            
            ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //提供一个 IP 地址，指示服务器应侦听所有网络接口上的客户端活动
            IPAddress ip = IPAddress.Any;
            //IPAddress ip = IPAddress.Parse("127.0.0.1"); 
            ServerInfo = new IPEndPoint(ip, this.GetPort());
            ServerSocket.Bind(ServerInfo);//将SOCKET接口和IP端口绑定
            ServerSocket.Listen(10);//开始监听，并且挂起数为10

            ClientSocket = new Socket[65535];//为客户端提供连接个数
            MsgBuffer = new byte[65535];//消息数据大小
            ClientNumb = 0;//数量从0开始统计

            ServerThread = new Thread(new ThreadStart(RecieveAccept));//将接受客户端连接的方法委托给线程
            ServerThread.Start();//线程开始运行

            CheckForIllegalCrossThreadCalls = false;//不捕获对错误线程的调用

            this.CmdStar.Enabled = false;
            this.CmdStop.Enabled = true;
            this.StateMsg.Text = "服务正在运行..." + ",运行端口为:" + this.GetPort().ToString();
            this.ClientList.Items.Add("服务于 " + DateTime.Now.ToString() + " 开始运行.");


        }//存放消息数据


        //接受客户端连接的方法
        private void RecieveAccept()
        {
            while (true)
            {
                //Accept 以同步方式从侦听套接字的连接请求队列中提取第一个挂起的连接请求，然后创建并返回新的 Socket。
                //在阻止模式中，Accept 将一直处于阻止状态，直到传入的连接尝试排入队列。连接被接受后，原来的 Socket 继续将传入的连接请求排入队列，直到您关闭它。
                //ClientSocket[ClientNumb] = ServerSocket.Accept();

                //ClientSocket[ClientNumb].BeginReceive(MsgBuffer, 0, MsgBuffer.Length, SocketFlags.None,
                //    new AsyncCallback(RecieveCallBack), ClientSocket[ClientNumb]);
                //lock (this.ClientList)
                //{
                //    this.ClientList.Items.Add(ClientSocket[ClientNumb].RemoteEndPoint.ToString() + " 成功连接服务器.");
                //}
                //ClientNumb++;

                Socket skt = ServerSocket.Accept();
                byte[] qryBuffer = new byte[60];
                int requstHeader = ReceiveHeader(skt);
                string RequestStr = ReceiveDetail(skt, qryBuffer, requstHeader);
                //byte[] qryBuffer = new byte[40];

                //skt.Receive(qryBuffer, SocketFlags.None);

                //string a = Encoding.GetEncoding("utf-8").GetString(qryBuffer);
                string sConnectStr = " ";
                if (RequestStr.ToUpper() == "DbPwd".ToUpper())
                {
                    sConnectStr = server+","+database + "," + uid + "," + pwd;
                }

                byte[] b0 = Encoding.GetEncoding("utf-8").GetBytes(sConnectStr);
                skt.Send(b0, 0, b0.Length, SocketFlags.None);

                lock (this.ClientList)
                {
                    this.ClientList.Items.Add(skt.RemoteEndPoint.ToString() + " 成功连接服务器.");
                }
                ClientNumb++;
            }
        }


        public int ReceiveHeader(Socket socket)
        {
            int dataSize = -1;  // error 
            byte[] buffer = new byte[4];
            int bytesRead = socket.Receive(buffer, 4,
                    System.Net.Sockets.SocketFlags.None);
            if (4 == bytesRead)
            {
                dataSize = BitConverter.ToInt32(buffer, 0);
                //dataSize = IPAddress.NetworkToHostOrder(dataSize);
            }
            else { }
            return dataSize;
        }

        public string ReceiveDetail(Socket socket, byte[] buffer,
              int dataSize)
        {
            try
            {
                string response = "";
                int bytesReceived = 0;
                int totalBytesReceived = 0;
                while (0 < (bytesReceived =
                   socket.Receive(buffer, (dataSize - totalBytesReceived),
                               SocketFlags.None)))
                {
                    totalBytesReceived += bytesReceived;
                    ASCIIEncoding encoding = new ASCIIEncoding();
                    response += Encoding.GetEncoding("utf-8").GetString(buffer, 0, bytesReceived);
                }
                return response;
            }
            catch (Exception)
            {
                return "";
            }

        }


        //回发数据给客户端
        private void RecieveCallBack(IAsyncResult AR)
        {
            try
            {
                Socket RSocket = (Socket)AR.AsyncState;
                int REnd = RSocket.EndReceive(AR);
                //对每一个侦听的客户端端口信息进行接收和回发
                for (int i = 0; i < ClientNumb; i++)
                {
                    if (ClientSocket[i].Connected)
                    {
                        //回发数据到客户端
                        //ClientSocket[i].Send(MsgBuffer, 0, REnd, SocketFlags.None);
                        string sConnectStr = "sa,oracle";
                        byte[] b0 = Encoding.GetEncoding("utf-8").GetBytes(sConnectStr);
                        ClientSocket[i].Send(b0, 0, b0.Length, SocketFlags.None);
                    }
                    //同时接收客户端回发的数据，用于回发
                    //RSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, 0, new AsyncCallback(RecieveCallBack), RSocket);
                }
            }
            catch
            {
                throw;
            }

        }

        private void CmdStop_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("是否要停止服务?请注意,停止服务后所有的客户端将不能运行!", "提示信息", MessageBoxButtons.OKCancel, MessageBoxIcon.Question)==System.Windows.Forms.DialogResult.OK)
            {
                ServerThread.Abort();//线程终止
                ServerSocket.Close();//关闭socket

                this.CmdStar.Enabled = true;
                this.CmdStop.Enabled = false;
                this.StateMsg.Text = "等待运行...";
                this.ClientList.Items.Add("服务于 " + DateTime.Now.ToString() + " 停止运行.");

                this.Close();
            }




        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (ServerThread != null)
            {
                ServerThread.Abort();//线程终止
                ServerSocket.Close();//关闭SOCKET
            }
            Application.Exit();

        }

        private void PortSeting_Click(object sender, EventArgs e)
        {
            frmSetting fSetting = new frmSetting();
            fSetting.ShowDialog();
        }



        #region//创建对象及声明变量
        //创建NotifyIcon对象  
        NotifyIcon notifyicon = new NotifyIcon();
        //创建托盘图标对象  
        Icon ico = new Icon("image\\BrsService.ico");
        //创建托盘菜单对象  
        ContextMenu notifyContextMenu = new ContextMenu();

        private void frmSocketServer_SizeChanged(object sender, EventArgs e)
        {
            //判断是否选择的是最小化按钮  
            if (WindowState == FormWindowState.Minimized)
            {
                //托盘显示图标等于托盘图标对象  
                //注意notifyIcon1是控件的名字而不是对象的名字  
                notifyIcon1.Icon = ico;
                //隐藏任务栏区图标  
                this.ShowInTaskbar = false;

                //图标显示在托盘区  
                notifyicon.Visible = true;

            }
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            //判断是否已经最小化于托盘  
            if (WindowState == FormWindowState.Minimized)
            {
                //还原窗体显示  
                WindowState = FormWindowState.Normal;
                //激活窗体并给予它焦点  
                this.Activate();
                //任务栏区显示图标  
                this.ShowInTaskbar = true;
                //托盘区图标隐藏  
                notifyicon.Visible = false;
            }
        }
        #endregion

        private void btnHide_Click(object sender, EventArgs e)
        {
            //判断是否选择的是最小化按钮  
            WindowState = FormWindowState.Minimized;
            if (WindowState == FormWindowState.Minimized)
            {
                //托盘显示图标等于托盘图标对象  
                //注意notifyIcon1是控件的名字而不是对象的名字  
                notifyIcon1.Icon = ico;
                //隐藏任务栏区图标  
                this.ShowInTaskbar = false;

                //图标显示在托盘区  
                notifyicon.Visible = true;

            }
        }

    }
}
